package com.dxtx.widget;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;


import com.dxtx.common.R;
import com.dxtx.util.SimpleAnimListener;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by user on 2016/11/9.
 * 拖动QQ消息上的未读红点,就知道这个View是干什么的了
 */
public class PullPointFrameLayout extends FrameLayout {
    //原点,touch事件点
    private Point p1, p2;
    //确定 粘性曲线图形 的四个点
    private Point p3, p4, p5, p6;
    // p1到p2的距离
    private float distance;
    private float r1, maxRadio, r2;
    private Path path;
    private final float maxDistance = getResources().getDimension(R.dimen.point_max_distance);

    private List<Point> points;

    public PullPointFrameLayout(Context context) {
        super(context);
        init();
    }

    public PullPointFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public PullPointFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {

        r1 = maxRadio;
        r2 = maxRadio;

        points = new ArrayList<>();

        //测试加入8个点
//        addPoint(new Point(200, 200));
//        addPoint(new Point(200, 400));
//        addPoint(new Point(200, 600));
//        addPoint(new Point(200, 800));
//        addPoint(new Point(200, 1000));
//        addPoint(new Point(600, 200));
//        addPoint(new Point(600, 400));
//        addPoint(new Point(600, 600));
//        addPoint(new Point(600, 800));
//        addPoint(new Point(600, 1000));

        p2 = new Point();
        p3 = new Point();
        p4 = new Point();
        p5 = new Point();
        p6 = new Point();


//        radialGradient = new RadialGradient(200, 200, 200, new int[]{0xffffffff, 0xffffffff, 0xff24f7fa, 0x800000ff, 0x000000ff}, new float[]{0, 0.15f, 0.4f, 0.5f, 1}, Shader.TileMode.CLAMP);
    }


    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        for (Point p : points) {
            if (p == p1) {
                canvas.drawCircle(p.x, p.y, r1, p.p);
            } else {
                canvas.drawCircle(p.x, p.y, p.r, p.p);
            }
        }
        if (p1 != null && path != null) {
            canvas.drawPath(path, p1.p);
            canvas.drawCircle(p2.x, p2.y, r2, p1.p);
        }
    }

    private boolean redClear = false;
    private boolean accept = false;


    @Override
    public boolean dispatchTouchEvent(MotionEvent e) {
        switch (e.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                if (p1 != null) {//上次的动画还没完,不能
                    break;
                }
                for (Point p : points) {
                    float distance = (float) Math.sqrt((e.getX() - p.x) * (e.getX() - p.x) + (e.getY() - p.y) * (e.getY() - p.y));
                    if (distance <= p.r) {
                        p1 = p;
                        r2 = r1 = maxRadio;
                        accept = true;
                        break;
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (redClear || !accept) {
                    return true;
                }
                p2.set(e.getX(), e.getY());
                distance = (float) Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
                if (distance >= maxDistance) {
                    redClear = true;
                    accept = false;
                    actionFront();
                    return true;
                } else {
                    r1 = maxRadio - distance / maxDistance * maxRadio * 0.67f;//最大距离时,原点缩小到1/3
                }
                link();
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (!accept) {
                    return true;
                } else {
                    accept = false;
                }
                p2.set(e.getX(), e.getY());
                actionBack();
                distance = (float) Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
                if (!redClear && distance < maxDistance) {
                    actionBack();//没扯掉原点,回弹...
                }
                redClear = false;
                break;
        }
        super.dispatchTouchEvent(e);
        return true;
    }


    private void link() {
        float dx1, dy1, dx2, dy2, k;
        if (p2.x != p1.x) {
            k = (p2.y - p1.y) / (p2.x - p1.x);
            if (k != 0) {
                //求垂直线斜率,p3和p4则是(过点p1,斜率为k的)直线上两点,且与p1的距离时r1
                k = -1f / k;
                //k代表斜率,那么k=dy/dx
                //由 k²*dx²+dx²=r² 解得dx=√1/(k²+1)
                float m = (float) Math.sqrt(1 / (k * k + 1));
                dx1 = m * r1;
                dy1 = Math.abs(k) * dx1;
                dx2 = m * r2;
                dy2 = Math.abs(k) * dx2;
            } else {
                dx1 = r1;
                dx2 = r2;
                dy1 = dy2 = 0;
            }
        } else {
            k = 0;
            dx1 = dx2 = 0;
            dy1 = r1;
            dy2 = r2;
        }

        path = new Path();

        if (k >= 0) {
            p3.set(p1.x + dx1, p1.y + dy1);
            p4.set(p1.x - dx1, p1.y - dy1);

            p5.set(p2.x + dx2, p2.y + dy2);
            p6.set(p2.x - dx2, p2.y - dy2);
        } else {
            p3.set(p1.x + dx1, p1.y - dy1);
            p4.set(p1.x - dx1, p1.y + dy1);

            p5.set(p2.x + dx2, p2.y - dy2);
            p6.set(p2.x - dx2, p2.y + dy2);
        }

        //按p3-->p4-->p6-->p5-->p3建立封闭图形
        path.moveTo(p3.x, p3.y);
        path.lineTo(p4.x, p4.y);

        path.quadTo((p1.x + p2.x) / 2, (p2.y + p1.y) / 2, p6.x, p6.y);
        path.lineTo(p5.x, p5.y);

        path.quadTo((p1.x + p2.x) / 2, (p1.y + p2.y) / 2, p3.x, p3.y);

        path.close();

        invalidate();
    }

    //没扯掉原点,回弹...
    private void actionBack() {
        final float x0 = p2.x;
        final float y0 = p2.y;
        final float r01 = r1;
        final float r02 = r2;
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float v = (Float) animation.getAnimatedValue();
                p2.set((p1.x - x0) * v + x0, (p1.y - y0) * v + y0);
                r1 = (maxRadio - r01) * v + r01;
                r2 = r02 - r02 * v;
                link();
            }
        });
        animator.addListener(new SimpleAnimListener() {
            @Override
            public void onAnimationEnd(Animator animation) {
                r1 = r2 = maxRadio;
                redClear = false;
                p1 = null;
            }
        });
        animator.setDuration(250);
        animator.start();
    }

    //扯掉原点,爆炸...
    private void actionFront() {
        final float x0 = p1.x;
        final float y0 = p1.y;
        final float r0 = r1;
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float v = (Float) animation.getAnimatedValue();
                p1.set((p2.x - x0) * v + x0, (p2.y - y0) * v + y0);
                r1 = (maxRadio - r0) * v + r0;
                link();
            }
        });
        animator.addListener(new SimpleAnimListener() {
            @Override
            public void onAnimationEnd(Animator animation) {
                r1 = r2 = maxRadio;
                redClear = false;
                path = null;
                boom();
            }
        });
        animator.setDuration(250);
        animator.start();
    }

    private void boom() {
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float v = (Float) animation.getAnimatedValue();
                r1 = v * maxRadio*0.5f + maxRadio;
                p1.p.setAlpha((int) (255 - 255 * v));
                invalidate();
            }
        });
        animator.addListener(new SimpleAnimListener() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if (pointClearListener != null) {
                    pointClearListener.OnPointClear(p1);
                }
                points.remove(p1);
                p1 = null;
                invalidate();
            }
        });
        animator.setDuration(500);
        animator.start();
    }

    public class Point {
        public float x;
        public float y;
        public float r = getResources().getDimension(R.dimen.point_default_radio);//半径 默认10dp
        public int id;//id用于区别记录点,默认0
        private int color = Color.RED;//颜色 默认红
        private Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);

        public void set(float x, float y) {
            this.x = x;
            this.y = y;
        }

        public Point(float x, float y) {
            this.x = x;
            this.y = y;
            p.setColor(color);
        }

        public Point(float x, float y, float r) {
            this.x = x;
            this.y = y;
            this.r = r;
            p.setColor(color);
        }

        public Point(float x, float y, float r, int color) {
            this.x = x;
            this.y = y;
            this.r = r;
            this.color = color;
            p.setColor(color);
        }

        public Point(float x, float y, float r, int color, int id) {
            this.id = id;
            this.r = r;
            this.x = x;
            this.y = y;
            this.color = color;
            p.setColor(color);
        }

        public Point() {
            p.setColor(color);
        }
    }


    public void addPoint(float x, float y) {
        addPoint(new Point(x, y));
    }

    public void addPoint(Point p) {
        if (points.isEmpty() || maxRadio < p.r) {
            maxRadio = p.r;
        }
        points.add(p);
        invalidate();
    }

    public void removePoint(int index) {
        points.remove(index);
        if (!points.isEmpty()) {
            maxRadio = 0;
            for (Point p : points) {
                maxRadio = Math.max(maxRadio, p.r);
            }
        } else {
            maxRadio = 0;
        }
    }

    //------------------红点消失回调------------------
    private OnPointClearListener pointClearListener;

    public void setOnPointClearListener(OnPointClearListener l) {
        pointClearListener = l;
    }

    public interface OnPointClearListener {
        void OnPointClear(Point p);
    }
    //------------------红点消失回调------------------
}

